﻿using System;
using System.Globalization;
using System.Threading.Tasks;
using Windows.ApplicationModel.Resources;
using Windows.Devices.Geolocation;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Maps;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using BuddyTracker.Model;

namespace BuddyTracker.ViewModel.Helpers
{
    /// <summary>
    /// Helper class for device location.
    /// </summary>
    class LocationHelper
    {
        /// <summary>
        /// Access to the dictionary for messages.
        /// </summary>
        private ResourceLoader loader = new ResourceLoader();
        /// <summary>
        /// MapControl for manipulation, got it with dependency injection from the constructor.
        /// </summary>
        private MapControl _map;

        /// <summary>
        /// Modifier for map zoom.
        /// </summary>
        private const double MapModifier = 1.45;

        public LocationHelper(MapControl cmap)
        {
            _map = cmap; //dependancy injection
        }
        /// <summary>
        /// Async location getter.
        /// </summary>
        /// <returns>Current device location.</returns>
        public async Task<Geopoint> GetLocationAsync()
        {

            Geolocator geolocator = new Geolocator { DesiredAccuracyInMeters = 5 };

            try
            {
                Geoposition geoposition = await geolocator.GetGeopositionAsync(
                    maximumAge: TimeSpan.FromMinutes(5),
                    timeout: TimeSpan.FromSeconds(30) //giving it 30 seconds, before giving up!
                    );                
                return new Geopoint(new BasicGeoposition()
                {
                    Latitude = geoposition.Coordinate.Point.Position.Latitude,
                    Longitude = geoposition.Coordinate.Point.Position.Longitude
                });

            }
            catch (Exception ex)
            {
                if ((uint)ex.HResult == 0x80004004)
                {
                    MessageDialogHelper.ShowGPSOffMessage();
                }
                return null;
            }
        }


        public void SetMapStyle(int type)
        {
            switch (type)
            {
                case 1:
                    _map.Style = MapStyle.Aerial;
                    foreach (var e in _map.Children)
                    {
                        ((TextBlock)((StackPanel) e).Children[0]).Foreground = new SolidColorBrush(Colors.White);
                    }
                    break;
                case 2:
                    _map.Style = MapStyle.AerialWithRoads;
                    foreach (var e in _map.Children)
                    {
                        ((TextBlock)((StackPanel)e).Children[0]).Foreground = new SolidColorBrush(Colors.White);
                    }
                    break;
                case 3:
                    _map.Style = MapStyle.Terrain;
                    foreach (var e in _map.Children)
                    {
                        ((TextBlock)((StackPanel)e).Children[0]).Foreground = new SolidColorBrush(Colors.White);
                    }
                    break;
                case 4:
                    _map.Style = MapStyle.Road;
                    _map.Style = MapStyle.Road;
                    foreach (var e in _map.Children)
                    {
                        ((TextBlock)((StackPanel)e).Children[0]).Foreground = new SolidColorBrush(Colors.Black);
                    }
                    _map.DesiredPitch = 52;
                    _map.LandmarksVisible = true;
                    _map.PedestrianFeaturesVisible = true;
                    break;
                default:
                     _map.DesiredPitch = 0;
                    _map.LandmarksVisible = false;
                    _map.PedestrianFeaturesVisible = false;
                    _map.Style = MapStyle.Road;
                    foreach (var e in _map.Children)
                    {
                        ((TextBlock)((StackPanel)e).Children[0]).Foreground = new SolidColorBrush(Colors.Black);
                    }
                    break;
            }
        }

        /// <summary>
        /// Marks the user on the injected MapControl.
        /// </summary>
        /// <param name="t">User for displaying.</param>
        public void MarkBuddy(User t)
        {
            Image i = new Image();
            i.Width = 67;
            i.Height = 67;
            var bmap = new BitmapImage(new Uri("ms-appx:///Assets/mapiconbuddy.png"));
            i.Source = bmap;

            TextBlock tb = new TextBlock() {TextAlignment = TextAlignment.Center};
            tb.FontSize = 12;
            if (_map.Style == MapStyle.Road)
                tb.Foreground = new SolidColorBrush(Colors.Black);
            else
                tb.Foreground = new SolidColorBrush(Colors.White);
            tb.Text = t.ScreenName + Environment.NewLine + t.LastSeen.ToString("dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture);

            StackPanel s = new StackPanel();
            s.Children.Add(tb);
            s.Children.Add(i);

            s.Opacity = 0.87;

            MapControl.SetLocation(s, t.LastLocation);
            MapControl.SetNormalizedAnchorPoint(s, new Point(0.595, 0.937));

            _map.Children.Add(s);
            
        }

        /// <summary>
        /// Shows the passed location as users location and centers the map around it.
        /// </summary>
        /// <param name="g">Location for display/center.</param>
        /// <param name="desc">Description of the pinpoint. Usually 'My Location' or similar.</param>
        public async void ShowMyLocationCentered(Geopoint g, string desc)
        {
            
            Image i = new Image();
            i.Width = 67;
            i.Height = 67;
            var bmap = new BitmapImage(new Uri("ms-appx:///Assets/mapicon.png"));
            i.Source = bmap;

            TextBlock t = new TextBlock();
            t.FontSize = 12;
            t.Foreground = new SolidColorBrush(Colors.Black);
            t.Text = desc;

            StackPanel s = new StackPanel();
            s.Children.Add(t);
            s.Children.Add(i);

            s.Opacity = 0.80;

            MapControl.SetLocation(s, g);
            MapControl.SetNormalizedAnchorPoint(s, new Point(0.64, 0.897));

            _map.Children.Add(s);

            await _map.TrySetViewAsync(g, 5);
        }

        /// <summary>
        /// Clears the map of all the pinpoints, buddys or current users.
        /// </summary>
        public void Clear()
        {
            _map.Children.Clear();
        }

        /// <summary>
        /// Method for zooming on the map, just right so that all buddies are visible!
        /// </summary>
        public void Zoom()
        {
           
            // TODO

        }        
        /// <summary>
        /// center map on desired location
        /// </summary>
        /// <param name="geopoint">location</param>
        internal void ShowLocationCentered(Geopoint geopoint)
        {
            _map.Center = geopoint;
            _map.ZoomLevel = 12;
        }
    }
}
